package org.richfaces.renderkit.html; import java.awt.Rectangle; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.StringTokenizer; import javax.faces.FacesException; import javax.faces.application.ResourceDependencies; import javax.faces.application.ResourceDependency; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; import javax.faces.convert.Converter; import javax.faces.convert.ConverterException; import org.richfaces.cdk.annotations.JsfRenderer; import org.richfaces.component.AbstractImageSelectTool; import org.richfaces.javascript.JSObject; import org.richfaces.log.LogFactory; import org.richfaces.log.Logger; import org.richfaces.renderkit.RendererBase; import org.richfaces.ui.common.HtmlConstants; import org.richfaces.util.InputUtils; @JsfRenderer(family = AbstractImageSelectTool.COMPONENT_FAMILY, type = org.richfaces.renderkit.html.ImageSelectToolRenderer.RENDERER_TYPE) @ResourceDependencies({@ResourceDependency(library = "javax.faces", name = "jsf.js"), @ResourceDependency(name = "jquery.js", target = "head"), @ResourceDependency(name = "richfaces.js", target = "head"), @ResourceDependency(name = "richfaces-base-component.js", target = "head"), @ResourceDependency(name = "jquery.Jcrop.js", target = "head"), @ResourceDependency(name = "richfaces.imageSelectTool.js", target = "head"), @ResourceDependency(name = "richfaces.imageSelectTool.ecss", target = "head")}) public class ImageSelectToolRenderer extends RendererBase { // ------------------------------ FIELDS ------------------------------ public static final String RENDERER_TYPE = "org.richfaces.ImageSelectToolRenderer"; private Logger logger = LogFactory.getLogger(ImageSelectToolRenderer.class); // -------------------------- OTHER METHODS -------------------------- @Override public void doEncodeEnd(ResponseWriter writer, FacesContext context, UIComponent component) throws IOException { if (!(component instanceof AbstractImageSelectTool)) { return; } String clientId = component.getClientId(context); AbstractImageSelectTool imageSelectTool = (AbstractImageSelectTool) component; String inputId = getInputId(context, imageSelectTool); writer.startElement(HtmlConstants.DIV_ELEM, null); writer.writeAttribute(HtmlConstants.ID_ATTRIBUTE, clientId, HtmlConstants.ID_ATTRIBUTE); writer.startElement(HtmlConstants.INPUT_ELEM, component); writer.writeAttribute(HtmlConstants.ID_ATTRIBUTE, inputId, HtmlConstants.ID_ATTRIBUTE); writer.writeAttribute(HtmlConstants.TYPE_ATTR, "hidden", HtmlConstants.TYPE_ATTR); writer.writeAttribute(HtmlConstants.NAME_ATTRIBUTE, inputId, HtmlConstants.NAME_ATTRIBUTE); writer.writeAttribute(HtmlConstants.VALUE_ATTRIBUTE, getValueAsString(context, component), HtmlConstants.NAME_ATTRIBUTE); // writer.endElement(HtmlConstants.INPUT_ELEM); writer.startElement(HtmlConstants.SCRIPT_ELEM, null); writer.writeAttribute(HtmlConstants.TYPE_ATTR, "text/javascript", "type"); final Map<String, Object> options = getOptions(context, imageSelectTool); if (imageSelectTool.getWidgetVar() != null) { writer.write("var " + imageSelectTool.getWidgetVar() + "="); } writer.writeText(new JSObject("RichFaces.ui.ImageSelectTool", clientId, options), null); writer.writeText(";", null); writer.endElement(HtmlConstants.SCRIPT_ELEM); writer.endElement(HtmlConstants.DIV_ELEM); } @Override public Object getConvertedValue(FacesContext context, UIComponent component, Object o) throws ConverterException { AbstractImageSelectTool uiImageSelectTool = (AbstractImageSelectTool) component; Converter converter = getConverter(uiImageSelectTool); String valueString = (String) o; return converter.getAsObject(context, component, valueString); } public Converter getConverter(AbstractImageSelectTool component) { Converter converter = component.getConverter(); if (converter == null) { converter = new RectangleConverter(); } return converter; } public String getInputId(FacesContext context, AbstractImageSelectTool component) { return component.getClientId(context) + ":input"; } private void addOptionIfSet(String optionName, Object value, Map<String, Object> options) { if (value != null && value != "") { options.put(optionName, value); } } @Override protected void doDecode(FacesContext context, UIComponent component) { super.doDecode(context, component); AbstractImageSelectTool uiImageSelectTool; if (component instanceof AbstractImageSelectTool) { uiImageSelectTool = (AbstractImageSelectTool) component; } else { if (logger.isDebugEnabled()) { logger.debug("No decoding necessary since the component " + component.getId() + " is not an instance or a sub class of UIInplaceInput"); } return; } if (InputUtils.isDisabled(uiImageSelectTool) || InputUtils.isReadOnly(uiImageSelectTool)) { if (logger.isDebugEnabled()) { logger.debug(("No decoding necessary since the component " + component.getId() + " is disabled")); } return; } String inputId = getInputId(context, uiImageSelectTool); if (inputId == null) { throw new NullPointerException("component client id is null"); } Map<String, String> request = context.getExternalContext().getRequestParameterMap(); String newValue = request.get(inputId); if (newValue != null) { uiImageSelectTool.setSubmittedValue(newValue); } } protected Class<? extends UIComponent> getComponentClass() { return AbstractImageSelectTool.class; } protected Map<String, Object> getOptions(FacesContext context, AbstractImageSelectTool component) throws IOException { Map<String, Object> options = new HashMap<String, Object>(); addOptionIfSet("onchange", component.getOnchange(), options); addOptionIfSet("onselect", component.getOnselect(), options); Rectangle rect = (Rectangle) component.getValue(); if (rect != null) { Map<String, Object> selection = new HashMap<String, Object>(); selection.put("x", rect.x); selection.put("y", rect.y); selection.put("width", rect.width); selection.put("height", rect.height); addOptionIfSet("selection", selection, options); } addOptionIfSet("maxWidth", component.getMaxWidth(), options); addOptionIfSet("maxHeight", component.getMaxHeight(), options); addOptionIfSet("minWidth", component.getMinWidth(), options); addOptionIfSet("minHeight", component.getMinHeight(), options); addOptionIfSet("aspectRatio", component.getAspectRatio(), options); addOptionIfSet("backgroundColor", component.getBackgroundColor(), options); addOptionIfSet("backgroundOpacity", component.getBackgroundOpacity(), options); addOptionIfSet("trueSizeWidth", component.getTrueSizeWidth(), options); addOptionIfSet("trueSizeHeight", component.getTrueSizeHeight(), options); String forAttribute = component.getTarget(); UIComponent forComp; String forClientId; if (forAttribute == null || forAttribute.length() == 0) { forComp = component; while ((forComp = forComp.getParent()) != null) { if (forComp instanceof javax.faces.component.UIGraphic) { break; } } /** * We are not interested in UIViewRoot */ if (forComp != null && forComp.getParent() == null) { forComp = null; } } else { forComp = getUtils().findComponentFor(context, component.getParent(), forAttribute); } if (forComp == null) { throw new FacesException("could not find target for croptool " + component.getId()); } forClientId = forComp.getClientId(context); addOptionIfSet("targetId", forClientId, options); addOptionIfSet("inputId", getInputId(context, component), options); return options; } protected String getValueAsString(FacesContext context, UIComponent component) throws IOException { AbstractImageSelectTool uiImageSelectTool = (AbstractImageSelectTool) component; String valueString = (String) uiImageSelectTool.getSubmittedValue(); if (valueString == null) { Object value = uiImageSelectTool.getValue(); if (value != null) { Converter converter = getConverter(uiImageSelectTool); valueString = converter.getAsString(context, component, value); } } return valueString; } // -------------------------- INNER CLASSES -------------------------- private class RectangleConverter implements Converter { // ------------------------ INTERFACE METHODS ------------------------ // --------------------- Interface Converter --------------------- public Object getAsObject(FacesContext facesContext, UIComponent component, String s) { StringTokenizer tokenizer = new StringTokenizer(s, ";"); try { Integer x = Integer.parseInt(tokenizer.nextToken()); Integer y = Integer.parseInt(tokenizer.nextToken()); Integer w = Integer.parseInt(tokenizer.nextToken()); Integer h = Integer.parseInt(tokenizer.nextToken()); return new Rectangle(x, y, w, h); } catch (Exception e) { throw new ConverterException("conversion failure; allowed pattern X;Y;W;H", e); } } public String getAsString(FacesContext facesContext, UIComponent component, Object o) { if (!(o instanceof Rectangle)) { throw new ConverterException(o + " is not instance of java.awt.Rectangle"); } Rectangle r = (Rectangle) o; return r.x + ";" + r.y + ";" + r.width + ";" + r.height; } } }